package scenes;
import java.awt.Component;
import java.net.URL;

import javax.media.j3d.BranchGroup;
import javax.media.j3d.Group;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;

import scenebuilders.BehaviorBuilder;
import scenebuilders.LightsBuilder;
import scenebuilders.SceneBuilder;
import scenebuilders.WiredBuilder;
import anaglyph.AnaglyphFacade;


public class SceneFactory {
	double pi4 = Math.PI / 4.0d;
	double pi2 = Math.PI / 2.0d;
	Component component;
	AnaglyphFacade anaglyphFacade = null;

	// builders
	SceneBuilder sbStaticc;
	SceneBuilder sbDynamic;
	LightsBuilder lightsBuilder;
	BehaviorBuilder behaviorBuilder;
    		
	public SceneFactory(Component component, AnaglyphFacade anaglyphFacade) {
		this.component = component;
		this.anaglyphFacade = anaglyphFacade;
	}
		
	public BranchGroup CreateScene(int sid) {
		BranchGroup sceneRoot = new BranchGroup();
		sceneRoot.setCapability(BranchGroup.ALLOW_DETACH);				
		behaviorBuilder = new BehaviorBuilder(anaglyphFacade, sceneRoot);
		TransformGroup behaviorRoot = behaviorBuilder.GetBehaviorRoot();
		sbDynamic = new SceneBuilder(behaviorRoot, component);		
		sbStaticc = new SceneBuilder(sceneRoot, component);	
		lightsBuilder = new LightsBuilder(sceneRoot);
		
		switch (sid) {
		case 1: CreateScene1(); break;
		case 2: CreateScene2(); break;
		case 3: CreateScene3(); break;
		}
		lightsBuilder.CreateLights();		
		behaviorBuilder.AddBehavior(sceneRoot);
		sbStaticc.createBackground();
		sceneRoot.compile();
		return sceneRoot;
	}
		
	public int GetDefaultSID() {
		return 1;
	}
	
	private URL GetMyResource(String resourceName) {
		return getClass().getResource("/" + resourceName);
	}	
	
// SCENE 1 ////////////////////////////////////////////////////////////////////////////	
				
	public void CreateScene1() {
		URL kockaVelka = GetMyResource("Mona_Lisa_face.jpg");
		URL kockaMala = GetMyResource("abstrakt/051105_VAB_640.jpg");
		URL farebnaStena = GetMyResource("wall_farebny_625x625.jpg");
		URL koberec = GetMyResource("carpet.jpg");
		
		// dynamic part
		sbDynamic.rotX(+pi2).createTG();
		this.createWiredGeometry(sbDynamic.GetSceneRoot(), 0.7f);
		sbDynamic.useTexture(kockaVelka).addCube(0.5f);
		sbDynamic.useTexture(kockaMala);//useMaterial(1.0f,0.3f,0.2f,0.6f,20f);
		sbDynamic.moveToX(-1.6f).addCube(0.25f);
		sbDynamic.moveToX(+1.6f).addCube(0.25f);

		// static part
		float stenaSirka = 6;
		float pppp = (float) (stenaSirka / (2*Math.sqrt(2))); 
		sbStaticc.useTexture(farebnaStena);		
		sbStaticc.useMaterial(0.8f, 0.9f, 0.7f, 0.9f, 70f);	
		sbStaticc.moveTo(-pppp,0.0f,-pppp).rotY(+pi4).addRectPlane(stenaSirka, 6);
		sbStaticc.moveTo(+pppp,0.0f,-pppp).rotY(-pi4).addRectPlane(stenaSirka, 6);
		sbStaticc.shapeBuilder.SetMyTextureCellsCount(2, 2);
		sbStaticc.useTexture(koberec)
				 .moveToY(-2.5f).rotX(-pi2).rotZ(+pi4)
				 .addRectPlane(stenaSirka, stenaSirka);
		
		// lighting and behavior
		lightsBuilder.RegisterSpotLights(1,20f,80f);
		lightsBuilder.SetSpotLight(0, new Vector3f(0,-1,-1), new Point3f(0,2,0));
		behaviorBuilder.SetAll();
	}
	
	private void createWiredGeometry(Group sceneRoot, float scale) {
		Point3f[] vertexArray = { 
				new Point3f(-1, +1, -1), new Point3f(-1, -1, -1), /*0-1*/
				new Point3f(+1, -1, -1), new Point3f(+1, +1, -1), /*2-3*/
				new Point3f(-1, +1, +1), new Point3f(-1, -1, +1), /*4-5*/
				new Point3f(+1, -1, +1), new Point3f(+1, +1, +1), /*6-7*/
				new Point3f(0, 0, 2), new Point3f(0, 0, -2),	/*8-9*/
		};
		
		WiredBuilder wb = new WiredBuilder(sceneRoot); 
		wb.setVertexArray(scale, vertexArray);
		wb.setStripOfVertex(0, 1, 2, 3, 0);
		wb.setStripOfVertex(4, 5, 6, 7, 4);
		wb.setStripOfVertex(0, 4);
		wb.setStripOfVertex(1, 5);
		wb.setStripOfVertex(2, 6);
		wb.setStripOfVertex(3, 7);
		wb.setStripOfVertex(5, 8, 7); // strecha 1.1
		wb.setStripOfVertex(4, 8, 6); // strecha 1.2
		wb.setStripOfVertex(1, 9, 3); // strecha 2.1
		wb.setStripOfVertex(0, 9, 2); // strecha 2.2
	}	
	
// SCENE 2 ////////////////////////////////////////////////////////////////////////////	
	
	public void CreateScene2() {
		String sphereTextureName1 = "earth_16k small.jpg";
		String sphereTextureName2 = "earth_16k small.jpg";
		URL textureBackG = GetMyResource("earthmap1k.jpg");	
		URL[] sphereTextures = new URL[] {
				GetMyResource(sphereTextureName1),
				GetMyResource(sphereTextureName1),
				GetMyResource(sphereTextureName1),
				GetMyResource(sphereTextureName1),
				GetMyResource(sphereTextureName2),
				GetMyResource(sphereTextureName2),
				GetMyResource(sphereTextureName2),
				GetMyResource(sphereTextureName2),
		};
		float rr = 0.25f;
		Vector3f[] spherePosition = new Vector3f[] {
				new Vector3f(-2*rr,+2*rr,+8*rr),
				new Vector3f(-2*rr,-2*rr,+8*rr),
				new Vector3f(+2*rr,-2*rr,+8*rr),
				new Vector3f(+2*rr,+2*rr,+8*rr),
				new Vector3f(-6*rr,+6*rr,-3*rr),
				new Vector3f(-6*rr,-6*rr,-3*rr),
				new Vector3f(+6*rr,-6*rr,-3*rr),
				new Vector3f(+6*rr,+6*rr,-3*rr),				
		};

		// dynamic part
		sbDynamic.useMaterial(0.9f, 0.9f, 0.9f, 0.3f, 90f);
		for (int i=0; i<4; i++) {
			sbDynamic.
				useTexture(sphereTextures[i]).
				moveTo(spherePosition[i]).
				addSphere(0.2f);
		} 		
		
		// static part
		sbStaticc.useMaterial(0.9f, 0.9f, 0.9f, 0.3f, 90f);
		for (int i=4; i<8; i++) {
			sbStaticc.
				useTexture(sphereTextures[i]).
				moveTo(spherePosition[i]).
				addSphere(0.2f);
		}
		
		// earth background
		sbStaticc.useMaterial(0.9f, 0.9f, 0.9f, 0.5f, 40f).useTexture(textureBackG);
		sbStaticc.moveToZ(-8f).addRectPlane(20, 10);
		
		// lighting and behavior
		lightsBuilder.RegisterSpotLights(1,15f,90f);
		lightsBuilder.lpGlobal.direction = new Vector3f(0, -1, -1);
		lightsBuilder.SetSpotLight(0, new Vector3f(0,0,-1), new Point3f(3,-3,-3));
		behaviorBuilder.SetAllExcept(BehaviorBuilder.BehaviorType.rotate);
		// TODO: there was a problem with two spotlights, sometimes it showed only one spotlight  		
	}

// SCENE 3 /////////////////////////////////////////////////////////////////////////////
	
	public void CreateScene3() {	
		String cubeTextureName1 = "mramor/3334.jpg";
		String cubeTextureName2 = "mramor/88563.jpg";		
		URL textureBackG = GetMyResource("fractals/integrity_by_ladycompassion-d4bjza2.jpg");
		URL koberec = GetMyResource("carpet.jpg");
		URL[] cubeTextures = new URL[] {
				GetMyResource(cubeTextureName1),
				GetMyResource(cubeTextureName2),
				GetMyResource(cubeTextureName1),
				GetMyResource(cubeTextureName2),
				GetMyResource(cubeTextureName1),
				GetMyResource(cubeTextureName2),
				GetMyResource(cubeTextureName1),
				GetMyResource(cubeTextureName2),
		};		
		Color3f[] cubeColors = new Color3f[] {
				new Color3f(1.0f,1.0f,1.0f),
				new Color3f(1.0f,1.0f,1.0f),
				new Color3f(1.0f,1.0f,1.0f),
				new Color3f(1.0f,1.0f,1.0f),
				new Color3f(0.5f,1.0f,0.5f),
				new Color3f(1.0f,1.0f,1.0f),
				new Color3f(1.0f,1.0f,1.0f),
				new Color3f(0.5f,1.0f,0.5f),
		};				
		
		behaviorBuilder.SetAll();
		lightsBuilder.lpGlobal.direction = new Vector3f(0,-0.6f,-1f);		
		SceneBuilder sb = sbDynamic; 
		
		// background
		sb.rotX(+pi4/4).moveToZ(+3.5f).createTG();
		sb.moveToZ(-5).useMaterial(1f, 1f, 1f, 0.7f, 70f)
					.useTexture(textureBackG)
					.addRectPlane(11, 9);		
		
		// stonehenge
		float cubeDim = 0.25f;
		float cubeDimZ = 0.8f;		
		float carpetZ = -1.5f;		
		float polomer = 1.5f;
		float cubePosZ = carpetZ + cubeDimZ;
		sb.rotX(-pi2).createTG();		
		for (int i=0; i<8; i++) {
			double angle = 2*Math.PI*(i/8.0)+pi4/2.0f;
			float xpos = (float)(polomer*Math.cos(angle));
			float ypos = (float)(polomer*Math.sin(angle));
			sb
				.useMaterial(cubeColors[i], 0.8f, 20f)
				.useTexture(cubeTextures[i])
				.moveTo(xpos,ypos,cubePosZ)
				.rotZ(angle)				
				.addCube(cubeDim,cubeDim,cubeDimZ);
		}
		
		// carpet
		sb.shapeBuilder.SetMyTextureCellsCount(4, 4);
		sb.useTexture(koberec)
			.useMaterial(1f, 1f, 1f, 0.7f, 70f)
			.moveToZ(carpetZ).addRectPlane(9.5f, 6);		
	}					
}

// Alyssa Miller